package com.hyperf.core.bean.result;

import com.alibaba.fastjson.JSON;
import com.hyperf.core.exception.ExceptionInfo;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serializable;
import java.util.function.Supplier;

/**
 * 通用结果集封装
 *
 * @author lizhaoyang
 */
@Getter
@Setter
@NoArgsConstructor
public class Result<T> implements Serializable {

    private static final long serialVersionUID = -6729674357234607097L;

    /**
     * 功能：是否成功
     */
    private boolean status;

    /**
     * 功能：返回码
     */
    private int code;

    /**
     * 功能：返回消息
     */
    private String message;

    /**
     * 功能：数据对象
     */
    private T data;

    public enum ResultEnum {
        /**
         * 成功-失败返回值
         */
        SUCCESS(200, "OK"),
        FAILURE(0,"ERROR");

        private final int code;
        private final String message;

        ResultEnum(int code, String message) {
            this.code = code;
            this.message = message;
        }

        public int getCode() {
            return code;
        }

        public String getMessage() {
            return message;
        }
    }

    /**
     * 功能：通过设置成功标识
     *
     * @param status
     */
    public Result(boolean status) {
        this.status = status;
    }

    /**
     * 功能：通过成功标志和数据对象来构造结果
     *
     * @param status
     * @param data
     */
    public Result(boolean status, T data) {
        this(status);
        this.data = data;
    }

    /**
     * 功能：通过成功标识返回的数据结果 和异常信息来构造对象
     *
     * @param status
     * @param code
     * @param message
     */
    public Result(boolean status, int code, String message) {
        this(status);
        this.code = code;
        this.message = message;
    }

    /**
     * 功能：通过成功标识返回的数据结果 和异常信息来构造对象
     *
     * @param status
     * @param code
     * @param message
     * @param data
     */
    public Result(boolean status, int code, String message, T data) {
        this(status, code, message);
        this.data = data;
    }

    /**
     * 功能：返回空的 Result
     *
     * @param <R>
     * @return
     */
    public static <R> Result<R> successData() {
        return new Result<>(true, ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage());
    }

    /**
     * 功能：返回空的 Result
     *
     * @param message
     * @param <R>
     * @return
     */
    public static <R> Result<R> successData(String message) {
        return new Result<>(true, ResultEnum.SUCCESS.getCode(), message);
    }

    /**
     * 功能：返回空的 Result
     *
     * @param <R>
     * @return
     */
    public static <R> Result<R> successData(int code, String message) {
        return new Result<>(true, code, message);
    }

    /**
     * 功能：返回success Result
     *
     * @param data
     * @param <R>
     * @return
     */
    public static <R> Result<R> successData(R data) {
        return new Result<>(true, ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), data);
    }

    /**
     * 功能：返回success Result
     *
     * @param supplier
     * @param <R>
     * @return
     */
    public static <R> Result<R> successData(Supplier<R> supplier) {
        return successData(supplier.get());
    }

    /**
     * 功能：返回failure Result
     *
     * @param <R>
     * @return
     */
    public static <R> Result<R> failureData() {
        return new Result<>(false, ResultEnum.FAILURE.getCode(), ResultEnum.FAILURE.getMessage());
    }

    /**
     * 功能：返回failure Result
     *
     * @param <R>
     * @return
     */
    public static <R> Result<R> failureData(String message) {
        return new Result<>(false, ResultEnum.FAILURE.getCode(), message);
    }

    /**
     * 功能：返回failure Result
     *
     * @param <R>
     * @return
     */
    public static <R> Result<R> failureData(int code, String message) {
        return new Result<>(false, code, message);
    }

    /**
     * 功能：返回failure Result
     *
     * @param <R>
     * @return
     */
    public static <R> Result<R> failureData(ExceptionInfo exceptionInfo) {
        return new Result<>(false, exceptionInfo.getErrorCode(), exceptionInfo.getErrorMessage());
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}
